/******************************************************************************
  SAGE - Scalable Adaptive Graphics Environment
 
  Module: ppm.cpp - loading ppm files
  Author : Rajvikram Singh
 
  Copyright (C) 2004 Electronic Visualization Laboratory,
  University of Illinois at Chicago
 
  This library is free software; you can redistribute it and/or modify it
  under the terms of the GNU Lesser General Public License as published by
  the Free Software Foundation; either Version 2.1 of the License, or
  (at your option) any later version.
 
  This library is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  License for more details.
 
  You should have received a copy of the GNU Lesser Public License along
  with this library; if not, write to the Free Software Foundation, Inc.,
  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
  Direct questions, comments etc about SAGE to bijeong@evl.uic.edu or 
  http://www.evl.uic.edu/cavern/forum/
 
 NOTE : This ppm.c file, has been modified by Rajvikram Singh. The modifications
   done so as to use the library for some network tests.

   A list of the modifications made is provided below :-
   
   [1]  The lib can now handle 1024x768 res files - previously restricted to 512x512
   [2]  The buffer used for storing the raw pixel information used a unsigned long
        integer (length=4 bytes)for storing 3 bytes of information. This had to be
        changed as there was an overhead of one byte per pixel ... extremely bad
        for the network tests. Now the library uses 3 bytes per pixel.

   [3]  Some extra copying to intermediate variables has been removed ... to speed
        up the code. But these changes are absolutely transparent.

*******************************************************************************/ 

#include <stdlib.h>
#include <string.h>
#include "ppm.h"

ppm ::   ppm(){
   widthOfImage = heightOfImage = imageType = 0;
   maxColorValue = 0;
   fp = NULL;
   picture = NULL;
   }

ppm::ppm(char *filename){
   widthOfImage = heightOfImage = imageType = 0;
   maxColorValue = 0;
   fp = NULL;
   picture = NULL;
   Read(filename);
   }

ppm :: ~ppm(){
   // raj was here
   //if (picture) delete picture;
   }


/* Reverses the RGBA order to AGBR and vice versa */
void ppm :: ReverseImage()
{

   unsigned long maxSize;
   maxSize = widthOfImage * heightOfImage * 4;

   char *data;
   data = (char *) picture;

   char temp1, temp2, temp3, temp4;

   for (unsigned long i = 0; i < maxSize; i+=4) {
      temp1 = data[i];
      temp2 = data[i+1];
      temp3 = data[i+2];
      temp4 = data[i+3];
      data[i] = temp4;
      data[i+1] = temp3;
      data[i+2] = temp2;
      data[i+3] = temp1;
   }

}



char * ppm::Read(char *filename)
{

   char imageFormat[4];

   fp = fopen(filename,"rb");
   if (fp == NULL) {
      std::cerr << "Cannot open image file " << filename << std::endl;
      exit(1);
   }
   fgets(imageFormat,4,fp);
   if ((strcmp(imageFormat,"P3\n")) && (strcmp(imageFormat,"P6\n"))){
      std::cerr << "Image file " << filename << " is not ppm format." << std::endl;
      exit(1);
   }      
   if (strcmp(imageFormat,"P3\n") == 0) imageType = PPMTEXT;
   else imageType = PPMRAWBITS;

   IgnoreCommentsIfAny();

   fscanf(fp,"%d",&widthOfImage);

   IgnoreCommentsIfAny();

   fscanf(fp,"%ld",&heightOfImage);

   IgnoreCommentsIfAny();

   fscanf(fp,"%ld",&maxColorValue);

   IgnoreCommentsIfAny();

   if (maxColorValue != 255) {
      std::cerr << "PPM file must be 24 bit color." << std::endl;
      exit(1);
   }

   if (picture) delete picture;
   picture = DoPPMLoad();

   if (picture == NULL) {
      std::cerr << "Image file corrupt." << std::endl;
      exit(1);
   }      
   fclose(fp);
   return (picture);
}

void ppm::IgnoreCommentsIfAny()

{
   char ch;
   char dummy[1000];
   FILE *imageFile;

   imageFile = fp;
   while(1) {
      ch = fgetc(imageFile);
      if (ch == '#') fgets(dummy, 1000, imageFile);
      else {
         ungetc(ch,imageFile);
         break;
      }
   }

}

char * ppm::DoPPMLoad()

{
   FILE *imageFile = fp;
   int imageFormat = imageType;

   int x,y;
   unsigned long location;
   char *aPicture;
   
   // The following initialization of texwidth and texheight was done by Raj (04/01/2001)
   // Not present in original files ... was causing failure for reading image
   // files greater that 512 x 512 pixs

   long texwidth=1024, texheight=768;
   
   if(widthOfImage<=128) texwidth = 128;
   else if(widthOfImage <= 256) texwidth = 256;
   else if(widthOfImage <= 512) texwidth = 512;

   if(heightOfImage<=128) texheight = 128;
   else if(heightOfImage <= 256) texheight = 256;
   else if(heightOfImage <= 512) texheight = 512;

   aPicture = new char[BYTES_PER_PIX * texwidth * texheight];
   memset(aPicture, 0, texwidth * texheight * BYTES_PER_PIX);

   fgetc(imageFile);   /* Strip CR */

   /* Now begin reading raster data. */

   for (y = 0; y< heightOfImage ; y++)
   {
      for (x = 0; x < widthOfImage; x++) {
      /*   if (imageFormat == PPMTEXT) {
            fscanf(imageFile,"%d",&dummy); red = (unsigned short) dummy;
            fscanf(imageFile,"%d",&dummy); green = (unsigned short) dummy;
            fscanf(imageFile,"%d",&dummy); blue =(unsigned short) dummy;
         } else 
      */   
         location = (BYTES_PER_PIX * (unsigned long) y) * widthOfImage + BYTES_PER_PIX * ((unsigned long) x);
         {
            fread((void*)(aPicture + location + 2),1,1,imageFile);
            fread((void*)(aPicture + location + 1),1,1,imageFile);
            fread((void*)(aPicture + location),1,1,imageFile);
            
         }

         if (feof(imageFile)) 
         { delete aPicture; return NULL;}
      }
   }
   widthOfImage = texwidth;
   heightOfImage = texheight;
   return aPicture;
}

